package com.androideasy.permissions

import android.Manifest
import android.annotation.SuppressLint
import android.app.AppOpsManager
import android.app.NotificationManager
import android.content.Context
import android.content.ContextWrapper
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.res.XmlResourceParser
import android.os.Build
import android.os.Environment
import android.provider.Settings
import android.text.TextUtils
import android.view.Surface
import androidx.fragment.app.FragmentActivity
import org.xmlpull.v1.XmlPullParserException
import java.io.IOException
import java.lang.IllegalArgumentException
import java.lang.IllegalStateException
import java.lang.RuntimeException
import java.lang.reflect.Field
import java.lang.reflect.InvocationTargetException
import java.util.ArrayList
import java.util.HashMap

class PermissionUtils {
    companion object {


        fun isAndroid12(): Boolean {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
        }

        fun isAndroid11(): Boolean {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
        }

        fun isAndroid10(): Boolean {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
        }

        fun isAndroid9(): Boolean {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
        }

        fun isAndroid8(): Boolean {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
        }

        fun isAndroid6(): Boolean {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        }

        fun isAndroid5(): Boolean {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
        }

        fun getAndroidNamespace(): String? {
            return "http://schemas.android.com/apk/res/android"
        }

        fun isDebugMode(context: Context): Boolean {
            return context.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
        }

        /**
         * 返回应用程序在清单文件中注册的权限
         */
        fun getManifestPermissions(context: Context): HashMap<String, Int>? {
            val manifestPermissions = HashMap<String, Int>()
            val parser: XmlResourceParser? = parseAndroidManifest(context)
            if (parser != null) {
                try {
                    do {
                        // 当前节点必须为标签头部
                        if (parser.eventType != XmlResourceParser.START_TAG) {
                            continue
                        }

                        // 当前标签必须为 uses-permission
                        if ("uses-permission" != parser.name) {
                            continue
                        }
                        manifestPermissions[parser.getAttributeValue(
                            getAndroidNamespace(),
                            "name"
                        )] =
                            parser.getAttributeIntValue(
                                getAndroidNamespace(),
                                "maxSdkVersion",
                                Int.MAX_VALUE
                            )
                    } while (parser.next() != XmlResourceParser.END_DOCUMENT)
                } catch (e: IOException) {
                    e.printStackTrace()
                } catch (e: XmlPullParserException) {
                    e.printStackTrace()
                } finally {
                    parser.close()
                }
            }
            if (manifestPermissions.isEmpty()) {
                try {
                    // 当清单文件没有注册任何权限的时候，那么这个数组对象就是空的
                    // https://github.com/getActivity/XXPermissions/issues/35
                    val requestedPermissions = context.packageManager.getPackageInfo(
                        context.packageName, PackageManager.GET_PERMISSIONS
                    ).requestedPermissions
                    if (requestedPermissions != null) {
                        for (permission in requestedPermissions) {
                            manifestPermissions[permission] = Int.MAX_VALUE
                        }
                    }
                } catch (e: PackageManager.NameNotFoundException) {
                    e.printStackTrace()
                }
            }
            return manifestPermissions
        }

        /**
         * 是否有存储权限
         */
        fun isGrantedStoragePermission(context: Context): Boolean {
            return if (isAndroid11()) {
                Environment.isExternalStorageManager()
            } else isGrantedPermissions(context,Permission.Group.STORAGE.asList())
        }

        /**
         * 是否有安装权限
         */
        fun isGrantedInstallPermission(context: Context): Boolean {
            return if (isAndroid8()) {
                context.packageManager.canRequestPackageInstalls()
            } else true
        }

        /**
         * 是否有悬浮窗权限
         */
        fun isGrantedWindowPermission(context: Context?): Boolean {
            return if (isAndroid6()) {
                Settings.canDrawOverlays(context)
            } else true
        }

        /**
         * 是否有系统设置权限
         */
        fun isGrantedSettingPermission(context: Context?): Boolean {
            return if (isAndroid6()) {
                Settings.System.canWrite(context)
            } else true
        }

        /**
         * 是否有通知栏权限
         */
        fun isGrantedNotifyPermission(context: Context): Boolean {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                return context.getSystemService(NotificationManager::class.java)
                    .areNotificationsEnabled()
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                // 参考 Support 库中的方法： NotificationManagerCompat.from(context).areNotificationsEnabled()
                val appOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
                return try {
                    val method = appOps.javaClass.getMethod(
                        "checkOpNoThrow",
                        Integer.TYPE, Integer.TYPE, String::class.java
                    )
                    val field = appOps.javaClass.getDeclaredField("OP_POST_NOTIFICATION")
                    val value = field[Int::class.java] as Int
                    method.invoke(
                        appOps, value, context.applicationInfo.uid,
                        context.packageName
                    ) as Int == AppOpsManager.MODE_ALLOWED
                } catch (e: NoSuchMethodException) {
                    e.printStackTrace()
                    true
                } catch (e: NoSuchFieldException) {
                    e.printStackTrace()
                    true
                } catch (e: InvocationTargetException) {
                    e.printStackTrace()
                    true
                } catch (e: IllegalAccessException) {
                    e.printStackTrace()
                    true
                } catch (e: RuntimeException) {
                    e.printStackTrace()
                    true
                }
            }
            return true
        }

        /**
         * 是否有读取包权限
         */
        fun isGrantedPackagePermission(context: Context): Boolean {
            if (isAndroid5()) {
                val appOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
                val mode: Int
                mode = if (isAndroid10()) {
                    appOps.unsafeCheckOpNoThrow(
                        AppOpsManager.OPSTR_GET_USAGE_STATS,
                        context.applicationInfo.uid, context.packageName
                    )
                } else {
                    appOps.checkOpNoThrow(
                        AppOpsManager.OPSTR_GET_USAGE_STATS,
                        context.applicationInfo.uid, context.packageName
                    )
                }
                return mode == AppOpsManager.MODE_ALLOWED
            }
            return true
        }

        /**
         * 判断某个权限集合是否包含特殊权限
         */
        fun containsSpecialPermission(permissions: List<String>?): Boolean {
            if (permissions == null || permissions.isEmpty()) {
                return false
            }
            for (permission in permissions) {
                if (isSpecialPermission(permission)) {
                    return true
                }
            }
            return false
        }

        /**
         * 判断某个权限是否是特殊权限
         */
        fun isSpecialPermission(permission: String): Boolean {
            return Permission.MANAGE_EXTERNAL_STORAGE == permission || Permission.REQUEST_INSTALL_PACKAGES == permission || Permission.SYSTEM_ALERT_WINDOW == permission || Permission.WRITE_SETTINGS == permission || Permission.NOTIFICATION_SERVICE == permission || Permission.PACKAGE_USAGE_STATS == permission
        }

        /**
         * 判断某些权限是否全部被授予
         */
        fun isGrantedPermissions(context: Context, permissions: List<String>): Boolean {
            if (permissions == null || permissions.isEmpty()) {
                return false
            }
            for (permission in permissions) {
                if (!isGrantedPermission(context, permission)) {
                    return false
                }
            }
            return true
        }

        /**
         * 获取没有授予的权限
         */
        fun getDeniedPermissions(context: Context, permissions: List<String>): List<String> {
            val deniedPermission: MutableList<String> = ArrayList(permissions.size)

            // 如果是安卓 6.0 以下版本就默认授予
            if (!isAndroid6()) {
                return deniedPermission
            }
            for (permission in permissions) {
                if (!isGrantedPermission(context, permission)) {
                    deniedPermission.add(permission)
                }
            }
            return deniedPermission
        }

        /**
         * 判断某个权限是否授予
         */
        fun isGrantedPermission(context: Context, permission: String): Boolean {
            // 检测通知栏权限
            if (Permission.NOTIFICATION_SERVICE == permission) {
                return isGrantedNotifyPermission(context)
            }

            // 检测获取读取包权限
            if (Permission.PACKAGE_USAGE_STATS == permission) {
                return isGrantedPackagePermission(context)
            }

            // 其他权限在 Android 6.0 以下版本就默认授予
            if (!isAndroid6()) {
                return true
            }

            // 检测存储权限
            if (Permission.MANAGE_EXTERNAL_STORAGE == permission) {
                return isGrantedStoragePermission(context)
            }

            // 检测安装权限
            if (Permission.REQUEST_INSTALL_PACKAGES == permission) {
                return isGrantedInstallPermission(context)
            }

            // 检测悬浮窗权限
            if (Permission.SYSTEM_ALERT_WINDOW == permission) {
                return isGrantedWindowPermission(context)
            }

            // 检测系统权限
            if (Permission.WRITE_SETTINGS == permission) {
                return isGrantedSettingPermission(context)
            }

            // 检测 Android 12 的三个新权限
            if (!isAndroid12()) {
                if (Permission.BLUETOOTH_SCAN == permission) {
                    return context.checkSelfPermission(Permission.ACCESS_COARSE_LOCATION) ==
                            PackageManager.PERMISSION_GRANTED
                }
                if (Permission.BLUETOOTH_CONNECT == permission || Permission.BLUETOOTH_ADVERTISE == permission) {
                    return true
                }
            }

            // 检测 Android 10 的三个新权限
            if (!isAndroid10()) {
                if (Permission.ACCESS_BACKGROUND_LOCATION == permission) {
                    return context.checkSelfPermission(Permission.ACCESS_FINE_LOCATION) ==
                            PackageManager.PERMISSION_GRANTED
                }
                if (Permission.ACTIVITY_RECOGNITION == permission) {
                    return context.checkSelfPermission(Permission.BODY_SENSORS) ==
                            PackageManager.PERMISSION_GRANTED
                }
                if (Permission.ACCESS_MEDIA_LOCATION == permission) {
                    return true
                }
            }

            // 检测 Android 9.0 的一个新权限
            if (!isAndroid9()) {
                if (Permission.ACCEPT_HANDOVER == permission) {
                    return true
                }
            }

            // 检测 Android 8.0 的两个新权限
            if (!isAndroid8()) {
                if (Permission.ANSWER_PHONE_CALLS == permission) {
                    return true
                }
                if (Permission.READ_PHONE_NUMBERS == permission) {
                    return context.checkSelfPermission(Permission.READ_PHONE_STATE) ==
                            PackageManager.PERMISSION_GRANTED
                }
            }
            return context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
        }

        /**
         * 优化权限回调结果
         */
        fun optimizePermissionResults(
            activity: FragmentActivity?,
            permissions: Array<String>,
            grantResults: IntArray
        ) {
            for (i in permissions.indices) {
                var recheck = false
                val permission = permissions[i]

                // 如果这个权限是特殊权限，那么就重新进行权限检测
                if (PermissionUtils.isSpecialPermission(permission)) {
                    recheck = true
                }

                // 重新检查 Android 12 的三个新权限
                if (!PermissionUtils.isAndroid12() &&
                    (Permission.BLUETOOTH_SCAN == permission || Permission.BLUETOOTH_CONNECT == permission || Permission.BLUETOOTH_ADVERTISE == permission)
                ) {
                    recheck = true
                }

                // 重新检查 Android 10.0 的三个新权限
                if (!PermissionUtils.isAndroid10() &&
                    (Permission.ACCESS_BACKGROUND_LOCATION == permission || Permission.ACTIVITY_RECOGNITION == permission || Permission.ACCESS_MEDIA_LOCATION == permission)
                ) {
                    recheck = true
                }

                // 重新检查 Android 9.0 的一个新权限
                if (!PermissionUtils.isAndroid9() && Permission.ACCEPT_HANDOVER == permission) {
                    recheck = true
                }

                // 重新检查 Android 8.0 的两个新权限
                if (!PermissionUtils.isAndroid8() &&
                    (Permission.ANSWER_PHONE_CALLS == permission || Permission.READ_PHONE_NUMBERS == permission)
                ) {
                    recheck = true
                }
                if (recheck) {
                    grantResults[i] = if (  isGrantedPermission(
                            activity!!,
                            permission
                        )
                    ) PackageManager.PERMISSION_GRANTED else PackageManager.PERMISSION_DENIED
                }
            }
        }

        /**
         * 在权限组中检查是否有某个权限是否被永久拒绝
         *
         * @param activity              Activity对象
         * @param permissions            请求的权限
         */
        fun isPermissionPermanentDenied(activity: FragmentActivity, permissions: List<String>): Boolean {
            for (permission in permissions) {
                if (isPermissionPermanentDenied(activity, permission)) {
                    return true
                }
            }
            return false
        }

        /**
         * 判断某个权限是否被永久拒绝
         *
         * @param activity              Activity对象
         * @param permission            请求的权限
         */
        fun isPermissionPermanentDenied(activity: FragmentActivity, permission: String): Boolean {
            if (!isAndroid6()) {
                return false
            }

            // 特殊权限不算，本身申请方式和危险权限申请方式不同，因为没有永久拒绝的选项，所以这里返回 false
            if (isSpecialPermission(permission)) {
                return false
            }

            // 检测 Android 12 的三个新权限
            if (!isAndroid12()) {
                if (Permission.BLUETOOTH_SCAN == permission) {
                    return !isGrantedPermission(activity, Permission.ACCESS_COARSE_LOCATION) &&
                            !activity.shouldShowRequestPermissionRationale(Permission.ACCESS_COARSE_LOCATION)
                }
                if (Permission.BLUETOOTH_CONNECT == permission || Permission.BLUETOOTH_ADVERTISE == permission) {
                    return false
                }
            }
            if (isAndroid10()) {

                // 重新检测后台定位权限是否永久拒绝
                if (Permission.ACCESS_BACKGROUND_LOCATION == permission &&
                    !isGrantedPermission(activity, Permission.ACCESS_BACKGROUND_LOCATION) &&
                    !isGrantedPermission(activity, Permission.ACCESS_FINE_LOCATION)
                ) {
                    return !activity.shouldShowRequestPermissionRationale(Permission.ACCESS_FINE_LOCATION)
                }
            }

            // 检测 Android 10 的三个新权限
            if (!isAndroid10()) {
                if (Permission.ACCESS_BACKGROUND_LOCATION == permission) {
                    return !isGrantedPermission(activity, Permission.ACCESS_FINE_LOCATION) &&
                            !activity.shouldShowRequestPermissionRationale(Permission.ACCESS_FINE_LOCATION)
                }
                if (Permission.ACTIVITY_RECOGNITION == permission) {
                    return !isGrantedPermission(activity, Permission.BODY_SENSORS) &&
                            !activity.shouldShowRequestPermissionRationale(Permission.BODY_SENSORS)
                }
                if (Permission.ACCESS_MEDIA_LOCATION == permission) {
                    return false
                }
            }

            // 检测 Android 9.0 的一个新权限
            if (!isAndroid9()) {
                if (Permission.ACCEPT_HANDOVER == permission) {
                    return false
                }
            }

            // 检测 Android 8.0 的两个新权限
            if (!isAndroid8()) {
                if (Permission.ANSWER_PHONE_CALLS == permission) {
                    return false
                }
                if (Permission.READ_PHONE_NUMBERS == permission) {
                    return !isGrantedPermission(activity, Permission.READ_PHONE_STATE) &&
                            !activity.shouldShowRequestPermissionRationale(Permission.READ_PHONE_STATE)
                }
            }
            return !isGrantedPermission(activity, permission) &&
                    !activity.shouldShowRequestPermissionRationale(permission)
        }

        /**
         * 获取没有授予的权限
         *
         * @param permissions           需要请求的权限组
         * @param grantResults          允许结果组
         */
        fun getDeniedPermissions(permissions: List<String>, grantResults: IntArray): List<String>? {
            val deniedPermissions: MutableList<String> = ArrayList()
            for (i in grantResults.indices) {
                // 把没有授予过的权限加入到集合中
                if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                    deniedPermissions.add(permissions!![i])
                }
            }
            return deniedPermissions
        }

        /**
         * 获取已授予的权限
         *
         * @param permissions       需要请求的权限组
         * @param grantResults      允许结果组
         */
        fun getGrantedPermissions(
            permissions: List<String>,
            grantResults: IntArray
        ): List<String>? {
            val grantedPermissions: MutableList<String> = ArrayList()
            for (i in grantResults.indices) {
                // 把授予过的权限加入到集合中
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    grantedPermissions.add(permissions[i])
                }
            }
            return grantedPermissions
        }


        fun <T> asArrayList(vararg array: T):  List<T> {
            val list = mutableListOf<T>() //<T>( )//array.size
            if (array == null || array.size == 0) {
                return list
            }
            for (t in array) {
                list.add(t)
            }
            return list
        }



        /**
         * 寻找上下文中的 Activity 对象
         */
        fun findActivity(context: Context?): FragmentActivity? {
            var context = context
            do {
                context = if (context is FragmentActivity) {
                    return context
                } else if (context is ContextWrapper) {
                    context.baseContext
                } else {
                    return null
                }
            } while (context != null)
            return null
        }

        /**
         * 获取当前应用 Apk 在 AssetManager 中的 Cookie，如果获取失败，则为 0
         */
        @SuppressLint("PrivateApi")
        fun findApkPathCookie(context: Context): Int {
            val assets = context.assets
            val apkPath = context.applicationInfo.sourceDir
            try {
                // 为什么不直接通过反射 AssetManager.findCookieForPath 方法来判断？因为这个 API 属于反射黑名单，反射执行不了
                // 为什么不直接通过反射 AssetManager.addAssetPathInternal 这个非隐藏的方法来判断？因为这个也反射不了
                val method = assets.javaClass.getDeclaredMethod(
                    "addAssetPath",
                    String::class.java
                )
                val cookie = method.invoke(assets, apkPath) as Int
                if (cookie != null) {
                    return cookie
                }
            } catch (e: NoSuchMethodException) {
                e.printStackTrace()
            } catch (e: IllegalAccessException) {
                e.printStackTrace()
            } catch (e: InvocationTargetException) {
                e.printStackTrace()
            }
            // 获取失败
            return 0
        }

        /**
         * 解析清单文件
         */
        fun parseAndroidManifest(context: Context): XmlResourceParser? {
            val cookie: Int = PermissionUtils.findApkPathCookie(context)
            if (cookie == 0) {
                // 如果 cookie 为 0，证明获取失败，直接 return
                return null
            }
            try {
                val parser = context.assets.openXmlResourceParser(cookie, "AndroidManifest.xml")
                do {
                    // 当前节点必须为标签头部
                    if (parser.eventType != XmlResourceParser.START_TAG) {
                        continue
                    }
                    if ("manifest" == parser.name) {
                        // 如果读取到的包名和当前应用的包名不是同一个的话，证明这个清单文件的内容不是当前应用的
                        // 具体案例：https://github.com/getActivity/XXPermissions/issues/102
                        if (TextUtils.equals(
                                context.packageName,
                                parser.getAttributeValue(null, "package")
                            )
                        ) {
                            return parser
                        }
                    }
                } while (parser.next() != XmlResourceParser.END_DOCUMENT)
            } catch (e: IOException) {
                e.printStackTrace()
            } catch (e: XmlPullParserException) {
                e.printStackTrace()
            }
            return null
        }

        /**
         * 判断是否适配了分区存储
         */
        fun isScopedStorage(context: Context): Boolean {
            try {
                val metaKey = "ScopedStorage"
                val metaData = context.packageManager.getApplicationInfo(
                    context.packageName, PackageManager.GET_META_DATA
                ).metaData
                if (metaData != null && metaData.containsKey(metaKey)) {
                    return java.lang.Boolean.parseBoolean(metaData[metaKey].toString())
                }
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
            }
            return false
        }

        /**
         * 判断 Activity 是否反方向旋转了
         */
        fun isActivityReverse(activity: FragmentActivity): Boolean {
            // 获取 Activity 旋转的角度
            val activityRotation: Int
            activityRotation = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                activity.display!!.rotation
            } else {
                activity.windowManager.defaultDisplay.rotation
            }
            return when (activityRotation) {
                Surface.ROTATION_180, Surface.ROTATION_270 -> true
                Surface.ROTATION_0, Surface.ROTATION_90 -> false
                else -> false
            }
        }

        /**
         * 检查 Activity 的状态是否正常
         *
         * @param checkMode         是否是检查模式
         * @return                  是否检查通过
         */
        fun checkActivityStatus(activity: FragmentActivity?, checkMode: Boolean): Boolean {
            // 检查当前 Activity 状态是否是正常的，如果不是则不请求权限
            if (activity == null) {
                if (checkMode) {
                    // Context 的实例必须是 Activity 对象
                    throw IllegalArgumentException("The instance of the context must be an activity object")
                }
                return false
            }
            if (activity.isFinishing) {
                if (checkMode) {
                    // 这个 Activity 对象当前不能是关闭状态，这种情况常出现在执行异步请求后申请权限
                    // 请自行在外层判断 Activity 状态是否正常之后再进入权限申请
                    throw IllegalStateException(
                        "The activity has been finishing, " +
                                "please manually determine the status of the activity"
                    )
                }
                return false
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed) {
                if (checkMode) {
                    // 这个 Activity 对象当前不能是销毁状态，这种情况常出现在执行异步请求后申请权限
                    // 请自行在外层判断 Activity 状态是否正常之后再进入权限申请
                    throw IllegalStateException(
                        "The activity has been destroyed, " +
                                "please manually determine the status of the activity"
                    )
                }
                return false
            }
            return true
        }

        /**
         * 检查传入的权限是否符合要求
         *
         * @param requestPermissions        请求的权限组
         * @param checkMode                 是否是检查模式
         * @return                          是否检查通过
         */
        fun checkPermissionArgument(
            requestPermissions: List<String>?,
            checkMode: Boolean
        ): Boolean {
            if (requestPermissions == null || requestPermissions.isEmpty()) {
                if (checkMode) {
                    // 不传权限，就想申请权限？
                    throw IllegalArgumentException("The requested permission cannot be empty")
                }
                return false
            }
            if (checkMode) {
                val allPermissions: MutableList<String> = ArrayList()
                val fields = Permission::class.java.declaredFields
                // 在开启代码混淆之后，反射 Permission 类中的字段会得到空的字段数组
                // 这个是因为编译后常量会在代码中直接引用，所以 Permission 常量字段在混淆的时候会被移除掉
                if (fields.size == 0) {
                    return true
                }
                for (field: Field in fields) {
                    if (String::class.java != field.type) {
                        continue
                    }
                    try {
                        allPermissions.add(field[null] as String)
                    } catch (e: IllegalAccessException) {
                        e.printStackTrace()
                    }
                }
                for (permission: String in requestPermissions) {
                    if (!allPermissions.contains(permission)) {
                        // 请不要申请危险权限和特殊权限之外的权限
                        throw IllegalArgumentException(
                            "The " + permission +
                                    " is not a dangerous permission or special permission, " +
                                    "please do not apply dynamically"
                        )
                    }
                }
            }
            return true
        }

        /**
         * 检查存储权限
         *
         * @param requestPermissions        请求的权限组
         */
        fun checkStoragePermission(context: Context, requestPermissions: List<String>) {
            // 如果请求的权限中没有包含外部存储相关的权限，那么就直接返回
            if ((!requestPermissions.contains(Permission.MANAGE_EXTERNAL_STORAGE) &&
                        !requestPermissions.contains(Permission.READ_EXTERNAL_STORAGE) &&
                        !requestPermissions.contains(Permission.WRITE_EXTERNAL_STORAGE))
            ) {
                return
            }

            // 是否适配了分区存储
            val scopedStorage = isScopedStorage(context)
            val parser = parseAndroidManifest(context) ?: return
            try {
                do {
                    // 当前节点必须为标签头部
                    if (parser.eventType != XmlResourceParser.START_TAG) {
                        continue
                    }

                    // 当前标签必须为 application
                    if ("application" != parser.name) {
                        continue
                    }
                    val targetSdkVersion = context.applicationInfo.targetSdkVersion
                    val requestLegacyExternalStorage = parser.getAttributeBooleanValue(
                        getAndroidNamespace(),
                        "requestLegacyExternalStorage", false
                    )
                    // 如果在已经适配 Android 10 的情况下
                    if (((targetSdkVersion >= Build.VERSION_CODES.Q) && !requestLegacyExternalStorage &&
                                (requestPermissions.contains(Permission.MANAGE_EXTERNAL_STORAGE) || !scopedStorage))
                    ) {
                        // 请在清单文件 Application 节点中注册 android:requestLegacyExternalStorage="true" 属性
                        // 否则就算申请了权限，也无法在 Android 10 的设备上正常读写外部存储上的文件
                        // 如果你的项目已经全面适配了分区存储，请在清单文件中注册一个 meta-data 属性
                        // <meta-data android:name="ScopedStorage" android:value="true" /> 来跳过该检查
                        throw IllegalStateException(
                            "Please register the android:requestLegacyExternalStorage=\"true\" " +
                                    "attribute in the AndroidManifest.xml file, otherwise it will cause incompatibility with the old version"
                        )
                    }

                    // 如果在已经适配 Android 11 的情况下
                    if (((targetSdkVersion >= Build.VERSION_CODES.R) &&
                                !requestPermissions.contains(Permission.MANAGE_EXTERNAL_STORAGE) && !scopedStorage)
                    ) {
                        // 1. 适配分区存储的特性，并在清单文件中注册一个 meta-data 属性
                        // <meta-data android:name="ScopedStorage" android:value="true" />
                        // 2. 如果不想适配分区存储，则需要使用 Permission.MANAGE_EXTERNAL_STORAGE 来申请权限
                        // 上面两种方式需要二选一，否则无法在 Android 11 的设备上正常读写外部存储上的文件
                        // 如果不知道该怎么选择，可以看文档：https://github.com/getActivity/XXPermissions/blob/master/HelpDoc
                        throw IllegalArgumentException(
                            ("The storage permission application is abnormal. If you have adapted the scope storage, " +
                                    "please register the <meta-data android:name=\"ScopedStorage\" android:value=\"true\" /> attribute in the AndroidManifest.xml file. " +
                                    "If there is no adaptation scope storage, please use MANAGE_EXTERNAL_STORAGE to apply for permission")
                        )
                    }

                    // 终止循环
                    break
                } while (parser.next() != XmlResourceParser.END_DOCUMENT)
            } catch (e: IOException) {
                e.printStackTrace()
            } catch (e: XmlPullParserException) {
                e.printStackTrace()
            } finally {
                parser.close()
            }
        }

        /**
         * 检查定位权限
         *
         * @param requestPermissions        请求的权限组
         */
        fun checkLocationPermission(context: Context, requestPermissions: List<String>) {
            if (context.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.S) {
                if (requestPermissions.contains(Permission.ACCESS_FINE_LOCATION) &&
                    !requestPermissions.contains(Permission.ACCESS_COARSE_LOCATION)
                ) {
                    // 如果您的应用以 Android 12 为目标平台并且您请求 ACCESS_FINE_LOCATION 权限
                    // 则还必须请求 ACCESS_COARSE_LOCATION 权限。您必须在单个运行时请求中包含这两项权限
                    // 如果您尝试仅请求 ACCESS_FINE_LOCATION，则系统会忽略该请求并在 Logcat 中记录以下错误消息：
                    // ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION
                    // 官方适配文档：https://developer.android.google.cn/about/versions/12/approximate-location
                    throw IllegalArgumentException(
                        ("If your app targets Android 12 or higher " +
                                "and requests the ACCESS_FINE_LOCATION runtime permission, " +
                                "you must also request the ACCESS_COARSE_LOCATION permission. " +
                                "You must include both permissions in a single runtime request.")
                    )
                }
            }

            // 判断是否包含后台定位权限
            if (!requestPermissions.contains(Permission.ACCESS_BACKGROUND_LOCATION)) {
                return
            }
            if (requestPermissions.contains(Permission.ACCESS_COARSE_LOCATION) &&
                !requestPermissions.contains(Permission.ACCESS_FINE_LOCATION)
            ) {
                // 申请后台定位权限可以不包含模糊定位权限，但是一定要包含精确定位权限，否则后台定位权限会无法申请
                // 也就是会导致无法弹出授权弹窗，经过实践，在 Android 12 上这个问题已经被解决了
                // 但是为了兼容 Android 12 以下的设备还是要那么做，否则在 Android 11 及以下设备会出现异常
                throw IllegalArgumentException(
                    "The application for background location permissions " +
                            "must include precise location permissions"
                )
            }
            for (permission: String in requestPermissions) {
                if (((Permission.ACCESS_FINE_LOCATION == permission) || (Permission.ACCESS_COARSE_LOCATION == permission) || (Permission.ACCESS_BACKGROUND_LOCATION == permission))) {
                    continue
                }
                throw IllegalArgumentException(
                    "Because it includes background location permissions, " +
                            "do not apply for permissions unrelated to location"
                )
            }
        }

        /**
         * 检查targetSdkVersion 是否符合要求
         *
         * @param requestPermissions            请求的权限组
         */
        fun checkTargetSdkVersion(context: Context, requestPermissions: List<String?>) {
            // targetSdk 最低版本要求
            val targetSdkMinVersion: Int
            if ((requestPermissions.contains(Permission.BLUETOOTH_SCAN) ||
                        requestPermissions.contains(Permission.BLUETOOTH_CONNECT) ||
                        requestPermissions.contains(Permission.BLUETOOTH_ADVERTISE))
            ) {
                targetSdkMinVersion = Build.VERSION_CODES.S
            } else if (requestPermissions.contains(Permission.MANAGE_EXTERNAL_STORAGE)) {
                // 必须设置 targetSdkVersion >= 30 才能正常检测权限，否则请使用 Permission.Group.STORAGE 来申请存储权限
                targetSdkMinVersion = Build.VERSION_CODES.R
            } else if (requestPermissions.contains(Permission.ACCEPT_HANDOVER)) {
                targetSdkMinVersion = Build.VERSION_CODES.P
            } else if ((requestPermissions.contains(Permission.ACCESS_BACKGROUND_LOCATION) ||
                        requestPermissions.contains(Permission.ACTIVITY_RECOGNITION) ||
                        requestPermissions.contains(Permission.ACCESS_MEDIA_LOCATION))
            ) {
                targetSdkMinVersion = Build.VERSION_CODES.Q
            } else if ((requestPermissions.contains(Permission.REQUEST_INSTALL_PACKAGES) ||
                        requestPermissions.contains(Permission.ANSWER_PHONE_CALLS) ||
                        requestPermissions.contains(Permission.READ_PHONE_NUMBERS))
            ) {
                targetSdkMinVersion = Build.VERSION_CODES.O
            } else {
                targetSdkMinVersion = Build.VERSION_CODES.M
            }

            // 必须设置正确的 targetSdkVersion 才能正常检测权限
            if (context.applicationInfo.targetSdkVersion < targetSdkMinVersion) {
                throw RuntimeException(
                    ("The targetSdkVersion SDK must be " + targetSdkMinVersion +
                            " or more, if you do not want to upgrade targetSdkVersion, " +
                            "please apply with the old permissions")
                )
            }
        }

        /**
         * 检查清单文件中所注册的权限是否正常
         *
         * @param requestPermissions            请求的权限组
         */
        fun checkManifestPermissions(context: Context, requestPermissions: List<String>) {
            val manifestPermissions = getManifestPermissions(context)
            if (manifestPermissions!!.isEmpty()) {
                throw IllegalStateException("No permissions are registered in the AndroidManifest.xml file")
            }
            val minSdkVersion =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) context.applicationInfo.minSdkVersion else Build.VERSION_CODES.M
            for (permission: String in requestPermissions) {
                if ((Permission.NOTIFICATION_SERVICE == permission)) {
                    // 不检测通知栏权限有没有在清单文件中注册，因为这个权限是框架虚拟出来的，有没有在清单文件中注册都没关系
                    continue
                }
                if (minSdkVersion < Build.VERSION_CODES.S) {
                    if ((Permission.BLUETOOTH_SCAN == permission)) {
                        checkManifestPermission(
                            manifestPermissions,
                            Manifest.permission.BLUETOOTH_ADMIN,
                            Build.VERSION_CODES.R
                        )
                        // 这是 Android 12 之前遗留的问题，获取扫描蓝牙的结果需要定位的权限
                        checkManifestPermission(
                            manifestPermissions,
                            Manifest.permission.ACCESS_COARSE_LOCATION,
                            Build.VERSION_CODES.R
                        )
                    }
                    if ((Permission.BLUETOOTH_CONNECT == permission)) {
                        checkManifestPermission(
                            manifestPermissions,
                            Manifest.permission.BLUETOOTH,
                            Build.VERSION_CODES.R
                        )
                    }
                    if ((Permission.BLUETOOTH_ADVERTISE == permission)) {
                        checkManifestPermission(
                            manifestPermissions,
                            Manifest.permission.BLUETOOTH_ADMIN,
                            Build.VERSION_CODES.R
                        )
                    }
                }
                if (minSdkVersion < Build.VERSION_CODES.R) {
                    if ((Permission.MANAGE_EXTERNAL_STORAGE == permission)) {
                        checkManifestPermission(
                            manifestPermissions,
                            Permission.READ_EXTERNAL_STORAGE,
                            Build.VERSION_CODES.Q
                        )
                        checkManifestPermission(
                            manifestPermissions,
                            Permission.WRITE_EXTERNAL_STORAGE,
                            Build.VERSION_CODES.Q
                        )
                    }
                }
                if (minSdkVersion < Build.VERSION_CODES.Q) {
                    if ((Permission.ACTIVITY_RECOGNITION == permission)) {
                        checkManifestPermission(
                            manifestPermissions,
                            Permission.BODY_SENSORS,
                            Build.VERSION_CODES.O
                        )
                    }
                }
                if (minSdkVersion < Build.VERSION_CODES.O) {
                    if ((Permission.READ_PHONE_NUMBERS == permission)) {
                        checkManifestPermission(
                            manifestPermissions,
                            Permission.READ_PHONE_STATE,
                            Build.VERSION_CODES.N_MR1
                        )
                    }
                }
                checkManifestPermission(manifestPermissions, permission, Int.MAX_VALUE)
            }
        }

        /**
         * 检查某个权限注册是否正常，如果是则会抛出异常
         *
         * @param manifestPermissions       清单权限组
         * @param checkPermission           被检查的权限
         * @param maxSdkVersion             最低要求的 maxSdkVersion
         */
        fun checkManifestPermission(
            manifestPermissions: HashMap<String, Int>?,
            checkPermission: String, maxSdkVersion: Int
        ) {
            if (!manifestPermissions!!.containsKey(checkPermission)) {
                // 动态申请的权限没有在清单文件中注册，分为以下两种情况：
                // 1. 如果你的项目没有在清单文件中注册这个权限，请直接在清单文件中注册一下即可
                // 2. 如果你的项目明明已注册这个权限，可以检查一下编译完成的 apk 包中是否包含该权限，如果里面没有，证明框架的判断是没有问题的
                //    一般是第三方 sdk 或者框架在清单文件中注册了 <uses-permission android:name="xxx" tools:node="remove"/> 导致的
                //    解决方式也很简单，通过在项目中注册 <uses-permission android:name="xxx" tools:node="replace"/> 即可替换掉原先的配置
                // 具体案例：https://github.com/getActivity/XXPermissions/issues/98
                throw IllegalStateException(
                    ("Please register permissions in the AndroidManifest.xml file " +
                            "<uses-permission android:name=\"" + checkPermission + "\" />")
                )
            }
            val manifestMaxSdkVersion = manifestPermissions.get(checkPermission) ?: return
            if (manifestMaxSdkVersion < maxSdkVersion) {
                // 清单文件中所注册的权限 maxSdkVersion 大小不符合最低要求，分为以下两种情况：
                // 1. 如果你的项目中注册了该属性，请根据报错提示修改 maxSdkVersion 属性值或者删除 maxSdkVersion 属性
                // 2. 如果你明明没有注册过 maxSdkVersion 属性，可以检查一下编译完成的 apk 包中是否有该属性，如果里面存在，证明框架的判断是没有问题的
                //    一般是第三方 sdk 或者框架在清单文件中注册了 <uses-permission android:name="xxx" android:maxSdkVersion="xx"/> 导致的
                //    解决方式也很简单，通过在项目中注册 <uses-permission android:name="xxx" tools:node="replace"/> 即可替换掉原先的配置
                // 具体案例：https://github.com/getActivity/XXPermissions/issues/98
                throw IllegalArgumentException(
                    ("The AndroidManifest.xml file " +
                            "<uses-permission android:name=\"" + checkPermission +
                            "\" android:maxSdkVersion=\"" + manifestMaxSdkVersion +
                            "\" /> does not meet the requirements, " +
                            (if (maxSdkVersion != Int.MAX_VALUE) "the minimum requirement for maxSdkVersion is $maxSdkVersion" else "please delete the android:maxSdkVersion=\"$manifestMaxSdkVersion\" attribute"))
                )
            }
        }

        /**
         * 处理和优化已经过时的权限
         *
         * @param requestPermissions            请求的权限组
         */
        fun optimizeDeprecatedPermission(requestPermissions: MutableList<String>) {
            if ((!isAndroid12() &&
                        requestPermissions.contains(Permission.BLUETOOTH_SCAN) &&
                        !requestPermissions.contains(Permission.ACCESS_COARSE_LOCATION))
            ) {
                // 自动添加定位权限，因为在低版本下获取蓝牙扫描的结果需要此权限
                requestPermissions.add(Permission.ACCESS_COARSE_LOCATION)
            }

            // 如果本次申请包含了 Android 12 蓝牙扫描权限
            if (!isAndroid12() && requestPermissions.contains(Permission.BLUETOOTH_SCAN)) {
                // 这是 Android 12 之前遗留的问题，扫描蓝牙需要定位的权限
                requestPermissions.add(Permission.ACCESS_COARSE_LOCATION)
            }

            // 如果本次申请包含了 Android 11 存储权限
            if (requestPermissions.contains(Permission.MANAGE_EXTERNAL_STORAGE)) {
                if (requestPermissions.contains(Permission.READ_EXTERNAL_STORAGE) ||
                    requestPermissions.contains(Permission.WRITE_EXTERNAL_STORAGE)
                ) {
                    // 检测是否有旧版的存储权限，有的话直接抛出异常，请不要自己动态申请这两个权限
                    throw IllegalArgumentException(
                        "If you have applied for MANAGE_EXTERNAL_STORAGE permissions, " +
                                "do not apply for the READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions"
                    )
                }
                if (!isAndroid11()) {
                    // 自动添加旧版的存储权限，因为旧版的系统不支持申请新版的存储权限
                    requestPermissions.add(Permission.READ_EXTERNAL_STORAGE)
                    requestPermissions.add(Permission.WRITE_EXTERNAL_STORAGE)
                }
            }
            if ((!isAndroid8() &&
                        requestPermissions.contains(Permission.READ_PHONE_NUMBERS) &&
                        !requestPermissions.contains(Permission.READ_PHONE_STATE))
            ) {
                // 自动添加旧版的读取电话号码权限，因为旧版的系统不支持申请新版的权限
                requestPermissions.add(Permission.READ_PHONE_STATE)
            }
            if ((!isAndroid10() &&
                        requestPermissions.contains(Permission.ACTIVITY_RECOGNITION) &&
                        !requestPermissions.contains(Permission.BODY_SENSORS))
            ) {
                // 自动添加传感器权限，因为这个权限是从 Android 10 开始才从传感器权限中剥离成独立权限
                requestPermissions.add(Permission.BODY_SENSORS)
            }
        }
    }
}